﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using UtilZ.Dotnet.Ex.Base;
using UtilZ.Dotnet.Ex.Communication.Base;
using UtilZ.Dotnet.Ex.Communication.Net.Base;
using UtilZ.Dotnet.Ex.Communication.Net.Tcp;
using UtilZ.Dotnet.Ex.Log;

namespace WpfApp
{
    /// <summary>
    /// TrestNetTcpListener.xaml 的交互逻辑
    /// </summary>
    public partial class TestNetTcpListener : Window
    {
        public TestNetTcpListener()
        {
            InitializeComponent();
        }
        private List<NetTcpClient> _tcpClients = new List<NetTcpClient>();

        private NetTcpListener _netTcpListener;
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            var redirectAppenderToUI = (RedirectAppender)Loger.GetAppenderByName(null, "RedirectToUI");
            if (redirectAppenderToUI != null)
            {
                redirectAppenderToUI.RedirectOuput += RedirectLogOutput;
            }

            int port = 3000;
            var initPara = new NetTcpListenerInitPara(port, 3);
            initPara.MaxConnections = 1;
            initPara.AcceptMode = ThreadMode.Async;
            initPara.SyncThreadName = "testNetTcpListener";
            this._netTcpListener = new NetTcpListener(this.AcceptSocketCallback, initPara);
        }



        private void AcceptSocketCallback(AcceptSocketArgs args)
        {
            var initPara = new NetTcpClientInitPara(new TestNetTcpListenerUnpacker(), args);
            var tcpClient = new NetTcpClient(initPara);
            tcpClient.ConnectChanged += TcpClient_ConnectChanged;
            this._tcpClients.Add(tcpClient);
            Loger.Info("AcceptSocketCallback...");
        }

        private void TcpClient_ConnectChanged(object sender, NetConnectedChangedArgs e)
        {
            if (e.Status == ConnectionStatus.Closed)
            {
                var client = (NetTcpClient)sender;
                this._tcpClients.Remove(client);
                client.Dispose();
            }
        }

        private void RedirectLogOutput(object sender, RedirectOuputArgs e)
        {
            string str;
            try
            {
                //str = string.Format("{0} {1}", e.Item.Time.ToString(LogConstant.DateTimeFormat), e.Item.Content);
                str = string.Format("{0} {1}", e.Item.Time.ToString("HH:mm:ss.ffffff"), e.Item.Content);

            }
            catch (Exception ex)
            {
                str = ex.Message;
            }

            logControl.AddLog(str, e.Item.Level);
        }

        private void btnStart_Click(object sender, RoutedEventArgs e)
        {
            this._netTcpListener.Start();

            Loger.Info($"启动监听 {NetHelper.GetIPPortString(this._netTcpListener.InitPara.ListenEndPoint)}");
        }

        private void btnStop_Click(object sender, RoutedEventArgs e)
        {
            this._netTcpListener.Stop();
            Loger.Info("this._netTcpListener.Stop();...");
        }

        private void btnDisconnect_Click(object sender, RoutedEventArgs e)
        {
            //if (this._tcpClient != null)
            //{
            //    this._tcpClient.Disconnect();
            //    this._tcpClient.Dispose();
            //    this._tcpClient = null;
            //}
        }

        private void btnSend_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                byte[] buffer = Encoding.UTF8.GetBytes($"abc123叶枫{TimeEx.GetTimestamp()}");
                foreach (var tcpClient in this._tcpClients)
                {
                    tcpClient.Send(buffer);
                }
            }
            catch (Exception ex)
            {
                Loger.Error(ex);
            }
        }
    }

    internal class TestNetTcpListenerUnpacker : UnpackerAbs
    {
        protected override int PrimitiveUnPackge(IUnpackerPara unpackerPara)
        {
            var netPara = (NetTcpUnpackerPara)unpackerPara;
            string str = Encoding.UTF8.GetString(netPara.Buffer, netPara.Offset, netPara.DataLength);
            Loger.Info($"收到数据\"{str}\"");
            return netPara.DataLength;
        }
    }
}
